#ifndef GENERATOR_CC
#define GENERATOR_CC

#include<string>
#include<fstream>
#include<sstream>
#include<iostream>
#include<algorithm>
#include<iterator>
#include<vector>
#include<map>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include <gsl/gsl_rng.h>
#include <gsl/gsl_randist.h>
#include "def.hpp"
#include "io.hpp"
#include "generator.hpp"
#include "generator_multinomial.hpp"
#include "generator_dirichlet.hpp"
#include "generator_polya.hpp"

using namespace std;
int Generator(){
  // This is the main program for "Generator"
  int (*GeneratorModel)(gsl_rng*);
  /* Determine which generator to use */
  if(PuzaDEF::Instance()->currentGeneratorType == GE_MULTINOMIAL){
    GeneratorModel = &GE_Multinomial;
    // prepare memory
    PuzaDEF::Instance()->GE_Multinomial_Data = new unsigned int[PuzaDEF::Instance()->GE_Multinomial_K];
  }
  if(PuzaDEF::Instance()->currentGeneratorType == GE_DIRICHLET){
    GeneratorModel = &GE_Dirichlet;
    // prepare memory
    PuzaDEF::Instance()->GE_Dirichlet_Data = new double[PuzaDEF::Instance()->GE_Dirichlet_K];
  }
  if(PuzaDEF::Instance()->currentGeneratorType == GE_POLYA){
    GeneratorModel = &GE_Polya;
    // prepare memory       
    PuzaDEF::Instance()->GE_Polya_Data = new unsigned int[PuzaDEF::Instance()->GE_Polya_K];
  }  

  // prepare random number generator
  gsl_rng *ge_gBaseRand;
  unsigned long ge_randSeed;

  ge_gBaseRand = gsl_rng_alloc(gsl_rng_mt19937);   /* specifying to use Mersenne twister MT-19937 as the uniform PRNG */
  ge_randSeed = rand();                    /* returns a non-negative integer */
  gsl_rng_set (ge_gBaseRand, ge_randSeed);    /* seed the PRNG */

  // run generator
  (*GeneratorModel)(ge_gBaseRand);

  // clean
  gsl_rng_free(ge_gBaseRand);
  return 0;
}

#endif
